﻿using Bootloader.Servicers;
using Bootloader.Services;
using Bootloader.zlgcan;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime;
using System.Runtime.Remoting.Channels;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Bootloader.AppSettings;
using ZLGAPI;
using static Bootloader.Services.FileParser;
using static Bootloader.zlgcan.UDS_TP;
using System.IO;

namespace Bootloader
{
    // 通道枚举
    public enum DeviceChannel
    {
        CHANNEL_0 = 0,
        CHANNEL_1 = 1,
    }

    // CAN/CANFD枚举
    public enum CanSendMode
    {
        CAN = 0,
        CANFD = 1,
        CANFD_BRS = 2,
    }

    // 校验方式枚举
    public enum ChecksumMode
    {
        SELF_OR_SIG_CHECK = 0,// 自校验或通过验签
        CRC32 = 1,
        SHA256 = 2,
    }

    // CANFD DLC枚举
    public enum CanFD_DlcMode
    {
        DLC_8 = 0,// 固定DLC = 8
        DLC_Dynamic = 1, // 动态DLC最大 = 64
    }

    public partial class Windows : Form
    {
        public class CanMessage
        {
            public DateTime Timestamp { get; set; }
            public uint Id { get; set; }
            public string Direction { get; set; } // "Tx" 或 "Rx"
            public byte[] Data { get; set; }

            // 用于 DataGridView 显示的格式化数据
            public string DataString =>
                Data == null ? "" : string.Join(" ", Data.Select(b => b.ToString("X2")));
            public string TimestampString => Timestamp.ToString("HH:mm:ss.fff");
            public string IdString => $"0x{Id:X}";
        }

        private readonly AppConfig _appConfig = new AppConfig();
        private ZlgCanDevice _zlgDeviceHandle = null;// zlg设备句柄
        private UDS_TP _uds_tp = null;// ZUDS协议栈句柄
        private FirmwareFlasher _firmFlash = null;// 刷写类对象
        private FlashFile _appFile;// 刷写app数据
        private FlashFile _flashDriverFile;// 刷写FlashDriver数据
        private SigFile _sigFile;// 验签文件
        private string _securityDllPath;// 27解锁文件

        // 虚拟模式相关字段
        private readonly List<CanMessage> _logBuffer = new List<CanMessage>();
        private readonly object _bufferLock = new object();
        private bool _isProgramming = false; // 刷写状态标志
        private readonly ConcurrentQueue<CanMessage> _logQueue = new ConcurrentQueue<CanMessage>();

        public Windows()
        {
            InitializeComponent();

            // 初始化log显示控件 - 虚拟模式
            InitializeVirtualDataGridView();

            // 加载保存的配置
            _appConfig.Load();

            // 通道选择下拉数据源
            var channelOptions = new List<UserSelItem<DeviceChannel>>
            {
                new UserSelItem<DeviceChannel> { DisplayName = "通道0", Value = DeviceChannel.CHANNEL_0 },
                new UserSelItem<DeviceChannel> { DisplayName = "通道1", Value = DeviceChannel.CHANNEL_1 }
            };
            ChannelSel.DataSource = channelOptions;
            ChannelSel.DisplayMember = "DisplayName";
            ChannelSel.ValueMember = "Value";
            ChannelSel.DataBindings.Add(
                propertyName: nameof(ComboBox.SelectedIndex),
                dataSource: _appConfig,
                dataMember: nameof(_appConfig.ChannelSelIndex),
                formattingEnabled: false,
                updateMode: DataSourceUpdateMode.OnPropertyChanged
            );

            // 波特率选择下拉数据源
            var BatueRateOptions = new List<UserSelItem<CanSendMode>>
            {
                new UserSelItem<CanSendMode> { DisplayName = "CAN", Value = CanSendMode.CAN },
                new UserSelItem<CanSendMode> { DisplayName = "CANFD", Value = CanSendMode.CANFD },
                new UserSelItem<CanSendMode> { DisplayName = "CANFD加速", Value = CanSendMode.CANFD_BRS },
            };
            BauteRateSel.DataSource = BatueRateOptions;
            BauteRateSel.DisplayMember = "DisplayName";
            BauteRateSel.ValueMember = "Value";
            BauteRateSel.DataBindings.Add(// 属性绑定，用于保存用户选项
                propertyName: nameof(ComboBox.SelectedIndex),
                dataSource: _appConfig,
                dataMember: nameof(_appConfig.BaudRateSelIndex),
                formattingEnabled: false,
                updateMode: DataSourceUpdateMode.OnPropertyChanged
            );

            // 校验方式选择下拉数据源
            var ChecksumMethodOptions = new List<UserSelItem<ChecksumMode>>
            {
                new UserSelItem<ChecksumMode> { DisplayName = "ECU自校验或通过加载的验签", Value = ChecksumMode.SELF_OR_SIG_CHECK },
                new UserSelItem<ChecksumMode> { DisplayName = "CRC32校验", Value = ChecksumMode.CRC32 },
                new UserSelItem<ChecksumMode> { DisplayName = "SHA256校验", Value = ChecksumMode.SHA256 }
            };
            ChecksumMethodSel.DataSource = ChecksumMethodOptions;
            ChecksumMethodSel.DisplayMember = "DisplayName";
            ChecksumMethodSel.ValueMember = "Value";
            ChecksumMethodSel.DataBindings.Add(// 属性绑定，用于保存用户选项
                propertyName: nameof(ComboBox.SelectedIndex),
                dataSource: _appConfig,
                dataMember: nameof(_appConfig.ChecksumMethodSelIndex),
                formattingEnabled: false,
                updateMode: DataSourceUpdateMode.OnPropertyChanged
            );

            // 诊断协议选择下拉数据源
            var UDSAgreementOptions = new List<UserSelItem<CanFD_DlcMode>>
            {
                new UserSelItem<CanFD_DlcMode> { DisplayName = "固定DLC = 8", Value = CanFD_DlcMode.DLC_8 },
                //new UserSelItem<CanFD_DlcMode> { DisplayName = "固定DLC = 64", Value = CanFD_DlcMode.DLC_64 },
                new UserSelItem<CanFD_DlcMode> { DisplayName = "动态DLC最大 = 64", Value = CanFD_DlcMode.DLC_Dynamic }
            };
            UDSAgreementSel.DataSource = UDSAgreementOptions;
            UDSAgreementSel.DisplayMember = "DisplayName";
            UDSAgreementSel.ValueMember = "Value";
            UDSAgreementSel.DataBindings.Add(// 属性绑定，用于保存用户选项
                propertyName: nameof(ComboBox.SelectedIndex),
                dataSource: _appConfig,
                dataMember: nameof(_appConfig.UDSAgreementSelIndex),
                formattingEnabled: false,
                updateMode: DataSourceUpdateMode.OnPropertyChanged
            );

            // 块大小选择下拉数据源
            var MaxBlockSizeOptions = new List<UserSelItem<int>>
            {
                //new UserSelItem<int> { DisplayName = "512", Value = 512 },
                //new UserSelItem<int> { DisplayName = "1024", Value = 1024 },
                //new UserSelItem<int> { DisplayName = "2048", Value = 2048 },
                //new UserSelItem<int> { DisplayName = "4095", Value = 4095 }
            };
            MaxBlockSizeSel.DataSource = MaxBlockSizeOptions;
            MaxBlockSizeSel.DisplayMember = "DisplayName";
            MaxBlockSizeSel.ValueMember = "Value";
            //MaxBlockSizeSel.SelectedIndex = 1;

            PHYAddrText.DataBindings.Add(// 物理地址 属性绑定，用于保存用户选项
                propertyName: nameof(TextBox.Text),
                dataSource: _appConfig,
                dataMember: nameof(_appConfig.PHYAddrText),
                formattingEnabled: false,
                updateMode: DataSourceUpdateMode.OnPropertyChanged
            );

            FUNAddrText.DataBindings.Add(// 功能地址 属性绑定，用于保存用户选项
                propertyName: nameof(TextBox.Text),
                dataSource: _appConfig,
                dataMember: nameof(_appConfig.FUNAddrText),
                formattingEnabled: false,
                updateMode: DataSourceUpdateMode.OnPropertyChanged
            );

            RepAddrText.DataBindings.Add(// 响应地址 属性绑定，用于保存用户选项
                propertyName: nameof(TextBox.Text),
                dataSource: _appConfig,
                dataMember: nameof(_appConfig.REPAddrText),
                formattingEnabled: false,
                updateMode: DataSourceUpdateMode.OnPropertyChanged
            );

            AppFilePathText.DataBindings.Add(// APP文件 属性绑定，用于保存用户选项
                propertyName: nameof(TextBox.Text),
                dataSource: _appConfig,
                dataMember: nameof(_appConfig.AppFilePath),
                formattingEnabled: false,
                updateMode: DataSourceUpdateMode.OnPropertyChanged
            );

            FlashDriverFilePathText.DataBindings.Add(// FlashDriver文件 属性绑定，用于保存用户选项
                propertyName: nameof(TextBox.Text),
                dataSource: _appConfig,
                dataMember: nameof(_appConfig.FlashdriverFilePath),
                formattingEnabled: false,
                updateMode: DataSourceUpdateMode.OnPropertyChanged
            );

            SigFilePathText.DataBindings.Add(// sig文件 属性绑定，用于保存用户选项
                propertyName: nameof(TextBox.Text),
                dataSource: _appConfig,
                dataMember: nameof(_appConfig.SigFilePath),
                formattingEnabled: false,
                updateMode: DataSourceUpdateMode.OnPropertyChanged
            );

            SecurityFilePathText.DataBindings.Add(// 安全算法dll文件 属性绑定，用于保存用户选项
                propertyName: nameof(TextBox.Text),
                dataSource: _appConfig,
                dataMember: nameof(_appConfig.DllFilePath),
                formattingEnabled: false,
                updateMode: DataSourceUpdateMode.OnPropertyChanged
            );

            LoadAllFile();
        }

        private void InitializeVirtualDataGridView()
        {
            // 启用虚拟模式
            CanLogGridView.VirtualMode = true;
            CanLogGridView.ReadOnly = true;
            CanLogGridView.AllowUserToAddRows = false;
            CanLogGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect;

            // 隐藏行标题
            CanLogGridView.RowHeadersVisible = false;

            // 手动添加列
            CanLogGridView.Columns.Add(new DataGridViewTextBoxColumn
            {
                Name = "Timestamp",
                HeaderText = "时间戳",
                Width = 90
            });

            CanLogGridView.Columns.Add(new DataGridViewTextBoxColumn
            {
                Name = "Id",
                HeaderText = "ID",
                Width = 50
            });

            CanLogGridView.Columns.Add(new DataGridViewTextBoxColumn
            {
                Name = "Direction",
                HeaderText = "方向",
                Width = 40
            });

            CanLogGridView.Columns.Add(new DataGridViewTextBoxColumn
            {
                Name = "Data",
                HeaderText = "数据",
                AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
            });

            // 绑定事件
            CanLogGridView.CellValueNeeded += CanLogGridView_CellValueNeeded;
        }

        private void CanLogGridView_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
        {
            int rowIndex = e.RowIndex;
            int colIndex = e.ColumnIndex;

            // 安全检查
            if (rowIndex < 0 || rowIndex >= _logBuffer.Count)
                return;

            CanMessage msg = null;
            lock (_bufferLock)
            {
                if (rowIndex < _logBuffer.Count)
                    msg = _logBuffer[rowIndex];
            }

            if (msg == null)
                return;

            switch (colIndex)
            {
                case 0:
                    e.Value = msg.Timestamp.ToString("HH:mm:ss.fff");
                    break;
                case 1:
                    e.Value = string.Format("0x{0:X}", msg.Id);
                    break;
                case 2:
                    e.Value = msg.Direction;
                    break;
                case 3:
                    if (msg.Data != null)
                    {
                        string hex = BitConverter.ToString(msg.Data);
                        e.Value = hex.Replace("-", " ");
                    }
                    else
                    {
                        e.Value = "";
                    }
                    break;
                default:
                    e.Value = "";
                    break;
            }
        }

        private void UpdateGridRowCount()
        {
            CanLogGridView.RowCount = _logBuffer.Count;

            // 自动滚动到底部（仅当用户在看底部时）
            if (_logBuffer.Count > 0)
            {
                int lastVisibleRow = CanLogGridView.FirstDisplayedScrollingRowIndex;
                int totalRows = _logBuffer.Count;
                if (lastVisibleRow >= totalRows - 2 || lastVisibleRow == 0)
                {
                    CanLogGridView.FirstDisplayedScrollingRowIndex = totalRows - 1;
                }
            }
        }

        private void AppendLog(CanMessage msg)
        {
            lock (_bufferLock)
            {
                _logBuffer.Add(msg);
            }

            // 在 UI 线程更新 RowCount
            if (CanLogGridView.InvokeRequired)
            {
                CanLogGridView.Invoke(new Action(() =>
                {
                    UpdateGridRowCount();
                }));
            }
            else
            {
                UpdateGridRowCount();
            }
        }

        private void groupBox1_Enter(object sender, EventArgs e)
        {

        }

        private void ChannelSel_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void PHYAddrInput(object sender, KeyPressEventArgs e)
        {
            //Debug.WriteLine($"KeyPress: '{e.KeyChar}' (ASCII: {(int)e.KeyChar})");
            // 1. 允许控制字符（退格键、删除键等）
            if (char.IsControl(e.KeyChar))
                return;

            // 2. 检查是否为有效的十六进制字符 (0-9, A-F, a-f)
            if (!Uri.IsHexDigit(e.KeyChar))
            {
                // 如果不是，取消输入
                e.Handled = true;
            }
        }

        private void OpenAppFileButton_Click(object sender, EventArgs e)
        {
            // 配置文件过滤器
            openFileAppDialog.Filter = "s19文件(*.s19)|*.s19";
            openFileAppDialog.Title = "请选择一个文件";

            // 显示文件浏览器
            DialogResult result = openFileAppDialog.ShowDialog();

            // 用户点击了“打开”
            if (result == DialogResult.OK)
            {
                OpenS19File(ref _appFile, ref AppFilePathText, ref AppFileInfoText, true, openFileAppDialog.FileName);
            }
        }

        private void OpenSigFileButton_Click(object sender, EventArgs e)
        {
            // 配置文件过滤器
            openFileAppDialog.Filter = "签名文件(*.sig)|*.sig";
            openFileAppDialog.Title = "请选择一个文件";

            // 显示文件浏览器
            DialogResult result = openFileAppDialog.ShowDialog();

            // 用户点击了“打开”
            if (result == DialogResult.OK)
            {
                OpenSigFile(ref _sigFile, ref SigFilePathText, ref SigFileInfoText, true, openFileAppDialog.FileName);
            }
        }
        private void OpenSigFile(ref SigFile fileHandle, ref TextBox textBoxPath, ref TextBox textBoxInfo, bool isThrowErro, string filePath)
        {
            try
            {
                fileHandle = FileParser.SigFileParser.ParseFromFile(filePath);

                if (_sigFile.Data.Count < 2)
                {
                    fileHandle = null;
                    throw new Exception("验签数量小于2个");
                }
                // 将选中的文件完整路径显示在 TextBox 中
                textBoxPath.Text = filePath;
                string fileInfo = "验签数量：" + _sigFile.Data.Count.ToString() + " 个";
                textBoxInfo.Text = fileInfo;
            }
            catch (Exception ex)
            {
                if (isThrowErro)
                {
                    MessageBox.Show(
                    this,
                    $"{ex.Message}",
                    "",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Warning
                    );
                }
                else
                {
                    textBoxInfo.Text = ex.Message;
                }
            }
        }

        private void OpenFlashDriverFileButton_Click(object sender, EventArgs e)
        {
            // 配置文件过滤器
            openFileAppDialog.Filter = "s19文件(*.s19)|*.s19";
            openFileAppDialog.Title = "请选择一个文件";

            // 显示文件浏览器
            DialogResult result = openFileAppDialog.ShowDialog();

            // 用户点击了“打开”
            if (result == DialogResult.OK)
            {
                OpenS19File(ref _flashDriverFile, ref FlashDriverFilePathText, ref FlashDriverFileInfoText, true, openFileAppDialog.FileName);
            }
        }

        private void OpenS19File(ref FlashFile fileHandle, ref TextBox textBoxPath, ref TextBox textBoxInfo, bool isThrowError, string filePath)
        {
            try
            {
                fileHandle = FileParser.S19Parser.ParseFile(filePath);

                // 将选中的文件完整路径显示在 TextBox 中
                textBoxPath.Text = filePath;
                string fileInfo;
                if (fileHandle.Data.Length > 1024 * 10)
                {
                    fileInfo = "文件大小：" + (fileHandle.Data.Length / 1024).ToString() + "KB\r\n";
                }
                else
                {
                    fileInfo = "文件大小：" + fileHandle.Data.Length.ToString() + "Byte\r\n";
                }
                fileInfo += "起始地址：0x" + fileHandle.StartAddr.ToString("X");
                textBoxInfo.Text = fileInfo;
            }
            catch (Exception ex)
            {
                if (isThrowError)
                {
                    MessageBox.Show(
                    this,
                    $"{ex.Message}",
                    "",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Warning
                    );
                }
                else
                {
                    textBoxInfo.Text = ex.Message;
                }
            }
        }

        private void SecurityFileButton_Click(object sender, EventArgs e)
        {
            // 配置文件过滤器
            openFileAppDialog.Filter = "dll文件(*.dll)|*.dll";
            openFileAppDialog.Title = "请选择一个文件";

            // 显示文件浏览器
            DialogResult result = openFileAppDialog.ShowDialog();

            // 用户点击了“打开”
            if (result == DialogResult.OK)
            {
                OpenDLLFile(ref _securityDllPath, ref SecurityFilePathText, ref SecurityFileInfoText, true, openFileAppDialog.FileName);
            }
        }

        private void OpenDLLFile(ref string objectFile, ref TextBox textBoxPath, ref TextBox textBoxInfo, bool isThrowError, string filePath)
        {
            try
            {
                ZLG27Algorithm.SetDllPath(filePath);
                objectFile = filePath;
                textBoxPath.Text = filePath;
                textBoxInfo.Text = "dll文件有效";
            }
            catch (Exception ex)
            {
                if (isThrowError)
                {
                    MessageBox.Show(
                    this,
                    $"{ex.Message}",
                    "",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Warning
                    );
                }
                else
                {
                    textBoxInfo.Text = ex.Message;
                }
            }
        }

        private async void StartDownloadButton_Click(object sender, EventArgs e)
        {
            // 提示用户先打开设备
            if (_zlgDeviceHandle == null)
            {
                bool ok = OpenDeviceFun();
                if (!ok)
                {
                    //MessageBox.Show(this, "请先打开设备");
                    return;
                }
            }

            // 提示要打开APP文件
            if (_appFile == null || _appFile.Data.Length == 0)
            {
                MessageBox.Show(this, "未选择APP刷写文件");
                return;
            }

            // 提示要打开Flashdriver文件
            if (_flashDriverFile == null || _flashDriverFile.Data.Length == 0)
            {
                MessageBox.Show(this, "未选择FlashDriver文件");
                return;
            }

            // 提示要打开dll文件
            if (_securityDllPath == null)
            {
                MessageBox.Show(this, "未加载27解锁DLL文件");
                return;
            }

            bool promIsSucces = false;
            var button = (Button)sender;
            // 创建刷写对象
            _firmFlash = new FirmwareFlasher(_uds_tp, _appFile, _flashDriverFile, _sigFile);

            // 设置校验方式
            _firmFlash.SetCheckSumMode((FirmwareFlasher.ChecksumMode)_appConfig.ChecksumMethodSelIndex);
            try
            {
                button.Text = "刷写中...";
                LogUpdateTimer.Enabled = true;
                flowLayoutPanel1.Enabled = false;

                // 开始刷写前暂停日志更新
                //_isProgramming = true;

                uint exPromCnt = 1;
                DownloadSuccedCntText.Text = "0";// 清除下载成功次数
                DownloadFailedCntText.Text = "0";// 清除下载失败次数
                // 从 MaskedTextBox 的 Text 属性读取字符串，并尝试转为 uint
                if (uint.TryParse(ExpectedPromCntText.Text, out uint promCnt))
                {
                    exPromCnt = promCnt;
                }
                else
                {
                    exPromCnt = 1;
                }
                for (uint i = 0; i < exPromCnt; i++)
                {
                    ClearCanLog();// 清除上一次log
                    // 开始下载
                    await _firmFlash.FlashStartAsync();
                    DownloadSuccedCntText.Text = (i + 1).ToString();// 下载成功次数
                    promIsSucces = true;
                }
                button.Text = "开始刷写";
                button.Enabled = true;
                LogUpdateTimer.Enabled = false;
                MessageBox.Show(this, "刷写成功！");
            }
            catch (ProgrammingException ex) when (ex.ErrorCode.HasValue)
            {
                // 编程自定义异常
                string msg = $"{ex.Message}\r\nNRC: {(ex.ErrorCode is byte b ? $"0x{b:X2}" : "N/A")}";
                MessageBox.Show(
                    this,
                    msg,
                    "",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Warning
                    );
            }
            catch (ProgrammingException ex)
            {
                // 编程自定义异常
                MessageBox.Show(
                    this,
                    $"{ex.Message}",
                    "",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Warning
                    );
            }
            catch (Exception ex)
            {
                // 一般是设备被占用，重开几次就好了
                MessageBox.Show(
                    //"请点击“关闭设备”，\n然后重新打开设备",
                    this,
                    $"{ex.Message}",
                    "",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Warning
                    );
            }
            finally
            {
                _firmFlash.FlashStop();
                button.Text = "开始刷写";
                button.Enabled = true;
                LogUpdateTimer.Enabled = false;
                ExpectedPromCntText.Enabled = true;
                flowLayoutPanel1.Enabled = true;

                // 结束刷写，恢复日志更新
                //_isProgramming = false;

                if (!promIsSucces)
                {
                    // 从当前文本解析失败次数，+1 后写回
                    if (int.TryParse(DownloadFailedCntText.Text, out int failCount))
                    {
                        DownloadFailedCntText.Text = (failCount + 1).ToString();
                    }
                    else
                    {
                        DownloadFailedCntText.Text = "1"; // 初始失败
                    }
                }
            }
        }

        private bool OpenDeviceFun()
        {
            // 检查UDS设置是否与CAN硬件配置匹配
            if (_appConfig.BaudRateSelIndex == (int)CanSendMode.CAN && _appConfig.UDSAgreementSelIndex != (int)CanFD_DlcMode.DLC_8)
            {
                MessageBox.Show(this, "配置错误，\nUDS为64位，但是CAN硬件配置为普通CAN\n请修改波特率或UDS模式配置");
                return false;
            }

            // 创建CAN设备对象
            _zlgDeviceHandle = new ZlgCanDevice(ZLGCAN.ZCAN_USBCANFD_200U, 0, (uint)_appConfig.ChannelSelIndex);
            //_zlgDeviceHandle = new ZlgCanDevice();

            // 设置使用CAN/CANFD
            _zlgDeviceHandle.SetCanfdMode((ZlgCanDevice.CanSendMode)_appConfig.BaudRateSelIndex);

            // 尝试打开设备
            bool ok = _zlgDeviceHandle.OpenDevice();
            if (ok)
            {
                // 打开成功更改显示文本
                //var button = (Button)sender;
                OpenDeviceButton.Text = "关闭设备";

                // 获取用户输入的诊断地址
                uint phyAddr = Convert.ToUInt32(_appConfig.PHYAddrText, 16);// 获取用户输入的物理地址
                uint funAddr = Convert.ToUInt32(_appConfig.FUNAddrText, 16);// 获取用户输入的功能地址
                uint repAddr = Convert.ToUInt32(_appConfig.REPAddrText, 16);// 获取用户输入的功能地址

                // 设置过滤器，只接收响应地址
                var canFilter = new List<uint>
                    {
                        repAddr
                    };
                _zlgDeviceHandle.SetCanFilter(canFilter);

                // 创建UDS对象
                _uds_tp = new UDS_TP(
                    sendFrame: _zlgDeviceHandle.SendFrame,
                    phyAddr: phyAddr,
                    funAddr: funAddr,
                    repAddr: repAddr,
                    udsMode: (UDS_TP.UDS_MODE)_appConfig.UDSAgreementSelIndex);
                // 将UDS消费回调函数，注入到dev类的接收回调函数中            // 注册日志回调（非阻塞）
                _uds_tp.SetUpdateLogCall((id, data, isTx) =>
                {
                    var msg = new CanMessage
                    {
                        Timestamp = DateTime.Now,
                        Id = id,
                        Direction = isTx ? "Tx" : "Rx",
                        Data = data ?? Array.Empty<byte>()
                    };
                    _logQueue.Enqueue(msg); // 非阻塞入队！
                });
                _zlgDeviceHandle.SetReceiveCallback(_uds_tp.OnReceive);
            }
            // 设备打开失败
            else
            {
                _zlgDeviceHandle = null;// 释放句柄，让GC自动回收
                MessageBox.Show(this, "设备打开失败！");
                return false;
            }
            return true;
        }

        private void OpenDeviceButton_Click(object sender, EventArgs e)
        {
            // 打开操作
            if (_zlgDeviceHandle == null)
            {
                OpenDeviceFun();
            }
            // 关闭设备操作
            else
            {
                // 取消对象的引用，让GC自动回收资源
                _firmFlash = null;
                _uds_tp.UDS_TP_DEInit();
                _uds_tp = null;
                // 尝试关闭设备
                bool ok = _zlgDeviceHandle.CloseDevice();
                if (ok)
                {
                    // 更改按键文本
                    var button = (Button)sender;
                    button.Text = "打开设备";
                    _zlgDeviceHandle = null;
                }
                else
                {
                    MessageBox.Show(this, "设备关闭失败！");
                }
            }

        }

        private void ClosingWindow(object sender, FormClosingEventArgs e)
        {
            this.Hide();// 先隐藏窗口再释放资源，提升用户体验
            _firmFlash = null;
            _uds_tp?.UDS_TP_DEInit();
            _zlgDeviceHandle?.CloseDevice();
        }

        private void LogUpdateTimer_Tick(object sender, EventArgs e)
        {
            // 如果正在刷写，跳过日志处理
            if (_isProgramming)
                return;

            // 队列为空，跳过处理
            if (_logQueue.IsEmpty)
                return;

            // 批量取出日志
            const int MAX_BATCH = 2000;// 每次最多取出2000条
            var batch = new List<CanMessage>(MAX_BATCH);

            while (batch.Count < MAX_BATCH && _logQueue.TryDequeue(out var msg))
            {
                batch.Add(msg);
            }

            // 如果有新日志，批量添加到虚拟缓冲区
            if (batch.Count > 0)
            {
                lock (_bufferLock)
                {
                    _logBuffer.AddRange(batch);

                    // 限制最大行数，防止内存爆炸
                    if (_logBuffer.Count > 100000)
                    {
                        int removeCount = Math.Max(0, _logBuffer.Count - 100000);
                        _logBuffer.RemoveRange(0, removeCount);
                    }
                }

                // 更新行数
                if (CanLogGridView.InvokeRequired)
                {
                    CanLogGridView.Invoke(new Action(() =>
                    {
                        UpdateGridRowCount();
                    }));
                }
                else
                {
                    UpdateGridRowCount();
                }
            }
        }

        // 清空log
        private void ClearCanLog()
        {
            // 清空数据源（线程安全）
            if (CanLogGridView.InvokeRequired)
            {
                CanLogGridView.Invoke(new Action(ClearCanLog));
                return;
            }

            lock (_bufferLock)
            {
                _logBuffer.Clear();
            }

            // 更新行数
            CanLogGridView.RowCount = 0;
        }

        // 重新加载所有文件
        private void LoadAllFile()
        {
            OpenS19File(ref _flashDriverFile, ref FlashDriverFilePathText, ref FlashDriverFileInfoText, false, _appConfig.FlashdriverFilePath);
            OpenS19File(ref _appFile, ref AppFilePathText, ref AppFileInfoText, false, _appConfig.AppFilePath);
            OpenSigFile(ref _sigFile, ref SigFilePathText, ref SigFileInfoText, false, _appConfig.SigFilePath);
            OpenDLLFile(ref _securityDllPath, ref SecurityFilePathText, ref SecurityFileInfoText, false, _appConfig.DllFilePath);
        }

        // 保存用户配置
        private void SaveSettingsConfig_Click(object sender, EventArgs e)
        {
            _appConfig.Save();
            MessageBox.Show(this, "配置保存成功");
        }

        private void SaveAsSettingsConfig_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveDialog = new SaveFileDialog
            {
                Filter = "JSON 配置文件|*.json",
                FileName = "settings.json",
                Title = "保存配置到..."
            };

            if (saveDialog.ShowDialog() == DialogResult.OK)
            {
                _appConfig.Save(saveDialog.FileName); // 这时 Save 会自动创建文件（目录也会自动建）
                MessageBox.Show(this, "配置保存成功");
            }
        }

        private void LoadSettingsConfig_Click(object sender, EventArgs e)
        {
            // 配置文件过滤器
            openFileAppDialog.Filter = "配置文件(*.json)|*.json";
            openFileAppDialog.Title = "请选择一个文件";

            // 显示文件浏览器
            DialogResult result = openFileAppDialog.ShowDialog();

            // 用户点击了“打开”
            if (result == DialogResult.OK)
            {
                _appConfig.Load(openFileAppDialog.FileName);
                LoadAllFile();
            }
        }
        private void DownInfoDragEnter(object sender, DragEventArgs e)
        {
            if (!e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                e.Effect = DragDropEffects.None;
                return;
            }

            // 获取当前选中的 TabPage
            var currentTab = DownloadInfoTab.SelectedTab;
            if (currentTab == null)
            {
                e.Effect = DragDropEffects.None;
                return;
            }

            // 从 Tag 获取允许的扩展名
            string allowedExtensions = currentTab.Tag?.ToString();
            if (string.IsNullOrEmpty(allowedExtensions))
            {
                e.Effect = DragDropEffects.Copy; // 默认允许所有
                return;
            }

            // 分割扩展名（如 ".bin,.json" → 数组）
            var extensions = allowedExtensions.Split(',')
                                              .Select(extension => extension.Trim().ToLower())
                                              .ToArray();

            // 获取拖入的第一个文件
            string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
            string ext = Path.GetExtension(files[0]).ToLower();

            // 判断是否允许
            if (extensions.Contains(ext))
            {
                e.Effect = DragDropEffects.Copy;  // 允许
            }
            else
            {
                e.Effect = DragDropEffects.None;  // 禁止
            }
        }

        private void DownInfoDragDrop(object sender, DragEventArgs e)
        {
            string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
            if (files.Length == 0) return;

            string filePath = files[0];
            var currentTab = DownloadInfoTab.SelectedTab;

            // 根据不同 TabPage 填入不同 TextBox
            switch (currentTab.Name)
            {
                case "AppFileTabPage":
                    OpenS19File(ref _appFile, ref AppFilePathText, ref AppFileInfoText, true, filePath);
                    //textBoxFirmware.Text = filePath;
                    break;
                case "SigFileTabPage":
                    OpenSigFile(ref _sigFile, ref SigFilePathText, ref SigFileInfoText, true, filePath);
                    //textBoxConfig.Text = filePath;
                    break;
                case "FlashDriverTabPage":
                    OpenS19File(ref _flashDriverFile, ref FlashDriverFilePathText, ref FlashDriverFileInfoText, true, filePath);
                    //textBoxScript.Text = filePath;
                    break;
                case "SecurityFileTabPage":
                    OpenDLLFile(ref _securityDllPath, ref SecurityFilePathText, ref SecurityFileInfoText, true, filePath);
                    //textBoxScript.Text = filePath;
                    break;
                case "DownInfoTabPage":
                    _appConfig.Load(filePath);
                    LoadAllFile();
                    //textBoxScript.Text = filePath;
                    break;
            }
        }

        private void AppVersionToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MessageBox.Show(this, "当前版本2025年11月22日第1版");
        }
    }
}

// 使用泛型
public class UserSelItem<T>
{
    public string DisplayName { get; set; }  // 显示给用户
    public T Value { get; set; }           // 泛型

    // 重写 ToString，确保 ComboBox 正确显示 DisplayName
    //public override string ToString() => DisplayName;
}